"""DHCP管理器."""

from datetime import datetime, timedelta
from typing import List, Optional

from sqlalchemy import select, and_, or_
from sqlalchemy.ext.asyncio import AsyncSession

from netsphere.models.dhcp import DHCPLease, DHCPReservation, DHCPScope
from netsphere.models.ipam import IPAddress


class DHCPManager:
    """DHCP管理器，负责DHCP作用域和租约管理."""
    
    def __init__(self, session: AsyncSession):
        """初始化DHCP管理器.
        
        Args:
            session: 数据库会话
        """
        self.session = session
    
    async def create_scope(
        self,
        name: str,
        subnet: str,
        netmask: str,
        start_ip: str,
        end_ip: str,
        gateway: str = None,
        dns_servers: List[str] = None,
        domain_name: str = None,
        lease_time: int = 3600,
        description: str = None,
    ) -> DHCPScope:
        """创建DHCP作用域.
        
        Args:
            name: 作用域名称
            subnet: 子网地址
            netmask: 子网掩码
            start_ip: 起始IP地址
            end_ip: 结束IP地址
            gateway: 默认网关
            dns_servers: DNS服务器列表
            domain_name: 域名
            lease_time: 租约时间（秒）
            description: 描述信息
            
        Returns:
            DHCPScope实例
        """
        scope = DHCPScope(
            name=name,
            subnet=subnet,
            netmask=netmask,
            start_ip=start_ip,
            end_ip=end_ip,
            gateway=gateway,
            dns_servers=",".join(dns_servers) if dns_servers else None,
            domain_name=domain_name,
            lease_time=lease_time,
            description=description,
        )
        self.session.add(scope)
        await self.session.commit()
        return scope
    
    async def create_reservation(
        self,
        scope_id: int,
        mac_address: str,
        ip_address: str,
        hostname: str = None,
        description: str = None,
    ) -> DHCPReservation:
        """创建DHCP保留地址.
        
        Args:
            scope_id: 作用域ID
            mac_address: MAC地址
            ip_address: IP地址
            hostname: 主机名
            description: 描述信息
            
        Returns:
            DHCPReservation实例
        """
        reservation = DHCPReservation(
            scope_id=scope_id,
            mac_address=mac_address,
            ip_address=ip_address,
            hostname=hostname,
            description=description,
        )
        self.session.add(reservation)
        await self.session.commit()
        return reservation
    
    async def get_scope_by_subnet(self, subnet: str) -> Optional[DHCPScope]:
        """根据子网获取作用域.
        
        Args:
            subnet: 子网地址
            
        Returns:
            DHCPScope实例或None
        """
        result = await self.session.execute(
            select(DHCPScope).where(DHCPScope.subnet == subnet)
        )
        return result.scalar_one_or_none()
    
    async def list_scopes(self, is_active: bool = None) -> List[DHCPScope]:
        """列出作用域.
        
        Args:
            is_active: 过滤活跃状态
            
        Returns:
            作用域列表
        """
        query = select(DHCPScope)
        if is_active is not None:
            query = query.where(DHCPScope.is_active == is_active)
        
        result = await self.session.execute(query)
        return list(result.scalars().all())
    
    async def get_scope_statistics(self, scope_id: int) -> dict:
        """获取作用域统计信息.
        
        Args:
            scope_id: 作用域ID
            
        Returns:
            统计信息字典
        """
        # 总地址数
        scope = await self.session.get(DHCPScope, scope_id)
        if not scope:
            raise ValueError(f"Scope {scope_id} not found")
        
        # 计算总地址数
        from ipaddress import ip_network
        net = ip_network(f"{scope.subnet}/{scope.netmask}")
        total_ips = len(list(net.hosts()))
        
        # 活跃租约数
        active_leases = await self.session.execute(
            select(DHCPLease).where(
                and_(
                    DHCPLease.scope_id == scope_id,
                    DHCPLease.state == "active",
                    DHCPLease.end_time > datetime.utcnow()
                )
            )
        )
        active_count = len(active_leases.scalars().all())
        
        # 保留地址数
        reservations = await self.session.execute(
            select(DHCPReservation).where(
                and_(
                    DHCPReservation.scope_id == scope_id,
                    DHCPReservation.is_active == True
                )
            )
        )
        reserved_count = len(reservations.scalars().all())
        
        return {
            "scope_id": scope_id,
            "total_addresses": total_ips,
            "active_leases": active_count,
            "reserved_addresses": reserved_count,
            "available_addresses": total_ips - active_count - reserved_count,
        }